package cn.itcast.bos.service.impl;

import cn.itcast.bos.domain.take_delivery.Order;
import cn.itcast.bos.domain.take_delivery.WayBill;
import cn.itcast.bos.index.WayBillIndexRepository;
import cn.itcast.bos.repository.WayBillRepository;
import cn.itcast.bos.service.WayBillService;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.*;
import org.elasticsearch.index.query.QueryStringQueryBuilder.Operator;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * Created by Think on 2017/9/27.
 */
@Service
@Transactional
public class WayBillServiceImpl implements WayBillService {


    @Autowired
    private WayBillRepository wayBillRepository;
    //引入索引库
    @Autowired
    private WayBillIndexRepository wayBillIndexRepository;

    @Override
    public void save(WayBill wayBill) {
        // 因为运单在运单表中表示唯一，且如果一旦创建，不能去修改运单号
        // 使用运单号查询运单数据
        WayBill persistWayBill = wayBillRepository.findByWayBillNum(wayBill.getWayBillNum());
        // 如果运单数据不存在，执行新增
        if (persistWayBill == null) {
            wayBill.setId(null);
            // 运单状态： 1 待发货、 2 派送中、3 已签收、4 异常
            wayBill.setSignStatus(1);
            wayBillRepository.save(wayBill);
            //同时向索引库中存放数据
            wayBillIndexRepository.save(wayBill);
        }
        // 如果运单数据存在，执行更新
        else {

            try {
                //运单存在，如果签收状态为1，表示状态为发货前，可以执行更新的操作，否则不能执行更新操作
                if (wayBill.getSignStatus() == 1) {
                    // 临时变量
                    Order order = persistWayBill.getOrder();
                    // 将页面传递的所有数据，赋值给持久化对象中
                    BeanUtils.copyProperties(persistWayBill, wayBill);
                    // 将临时变量，设置回persistWayBill
                    persistWayBill.setOrder(order);
                    // 运单状态： 1 待发货、 2 派送中、3 已签收、4 异常
                    persistWayBill.setSignStatus(1);
                    // 快照更新，更新持久化对象中的属性，就可以完成更新，更新的是persistWayBill

                    //同时向索引库中存放数据
                    wayBillIndexRepository.save(wayBill);
                }
                // 运单状态表示已经运输中，不能修改
                else {
                    throw new RuntimeException("运单已经发出，无法修改保存");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }


    }

    @Override
    public Page<WayBill> findAll(Pageable pageable) {
        Page<WayBill> page = wayBillRepository.findAll(pageable);
        return page;
    }

    @Override
    public WayBill findByWayBillNum(String wayBillNum) {
        return wayBillRepository.findByWayBillNum(wayBillNum);
    }

    @Override
    public void syncIndex() {
        //查询数据库所有记录
        List<WayBill> list = wayBillRepository.findAll();
        //同步到索引库
        wayBillIndexRepository.save(list);
    }

    // 如果没有指定查询条件：从数据库中查询所有
    // 如果指定条件查询：从索引库中查询结果
    @Override
    public Page<WayBill> findAll(WayBill wayBill, Pageable pageable) {
        // 如果没有指定查询条件：从数据库中查询所有
        if (StringUtils.isBlank(wayBill.getWayBillNum()) &&
                StringUtils.isBlank(wayBill.getSendAddress()) &&
                StringUtils.isBlank(wayBill.getRecAddress()) &&
                StringUtils.isBlank(wayBill.getSendProNum()) &&
                (wayBill.getSignStatus() == null || wayBill.getSignStatus() == 0)) {
            return wayBillRepository.findAll(pageable);
        }
        // 如果指定条件查询：从索引库中查询结果
        else {
            // 使用BoolQueryBuilder，用来拼装多个查询条件
            BoolQueryBuilder query = new BoolQueryBuilder();
            // 1:运单号：<input name="wayBillNum"   ----- 完全匹配
            if (StringUtils.isNotBlank(wayBill.getWayBillNum())) {
                QueryBuilder queryBuilder = new TermQueryBuilder("wayBillNum", wayBill.getWayBillNum());
                query.must(queryBuilder);
            }
            // 2:发货地：<input name="sendAddress"
            if (StringUtils.isNotBlank(wayBill.getSendAddress())) {
                QueryBuilder queryBuilder1 = new WildcardQueryBuilder("sendAddress", "*" + wayBill.getSendAddress() + "*");
                //queryStringQueryBuilder查询条件,是先把输入的字符串分词,再去索引库查询.避免输入词太长,索引库没有匹配词
                QueryBuilder queryBuilder2 = new QueryStringQueryBuilder(wayBill.getSendAddress()).field("sendAddress").defaultOperator(Operator.AND);// 将搜素的结果进行合并
                BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
                queryBuilder.should(queryBuilder1).should(queryBuilder2);
                query.must(queryBuilder);
            }

            // 3:收货地：<input name="recAddress"
            if (StringUtils.isNotBlank(wayBill.getRecAddress())) {
                QueryBuilder queryBuilder1 = new WildcardQueryBuilder("recAddress", "*" + wayBill.getRecAddress() + "*");
                QueryBuilder queryBuilder2 = new QueryStringQueryBuilder(wayBill.getRecAddress()).field("recAddress").defaultOperator(Operator.AND);// 将搜素的结果进行合并
                BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
                queryBuilder.should(queryBuilder1).should(queryBuilder2);
                query.must(queryBuilder);
            }

            // 4:快递产品类型：<select class="easyui-combobox" style="width:150px" name="sendProNum">
            if (StringUtils.isNotBlank(wayBill.getSendProNum())) {
                QueryBuilder queryBuilder = new TermQueryBuilder("sendProNum", wayBill.getSendProNum());
                query.must(queryBuilder);
            }

            // 5:运单状态：<select class="easyui-combobox" style="width:150px" name="signStatus">
            if (wayBill.getSignStatus() != null && wayBill.getSignStatus() != 0) {
                QueryBuilder queryBuilder = new TermQueryBuilder("signStatus", wayBill.getSignStatus());
                query.must(queryBuilder);
            }
            SearchQuery searchQuery = new NativeSearchQuery(query); // 拼装多个查询条件
            // 添加分页
            searchQuery.setPageable(pageable);
            return wayBillIndexRepository.search(searchQuery);
        }
    }
    // 用在报表技术上
    @Override
    public List<WayBill> findWayBills(WayBill wayBill) {
        // 如果没有指定查询条件：从数据库中查询所有
        if(StringUtils.isBlank(wayBill.getWayBillNum()) &&
                StringUtils.isBlank(wayBill.getSendAddress()) &&
                StringUtils.isBlank(wayBill.getRecAddress()) &&
                StringUtils.isBlank(wayBill.getSendProNum()) &&
                (wayBill.getSignStatus()==null || wayBill.getSignStatus()==0)){
            return wayBillRepository.findAll();
        }
        // 如果指定条件查询：从索引库中查询结果
        else{
            // 使用BoolQueryBuilder，用来拼装多个查询条件
            BoolQueryBuilder query = new BoolQueryBuilder();
            // 1:运单号：<input name="wayBillNum"   ----- 完全匹配
            if(StringUtils.isNotBlank(wayBill.getWayBillNum())){
                QueryBuilder queryBuilder = new TermQueryBuilder("wayBillNum", wayBill.getWayBillNum());
                query.must(queryBuilder);
            }
            // 2:发货地：<input name="sendAddress"
            if(StringUtils.isNotBlank(wayBill.getSendAddress())){
                QueryBuilder queryBuilder1 = new WildcardQueryBuilder("sendAddress", "*"+wayBill.getSendAddress()+"*");
                QueryBuilder queryBuilder2 = new QueryStringQueryBuilder(wayBill.getSendAddress()).field("sendAddress").defaultOperator(Operator.AND);// 将搜素的结果进行合并
                BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
                queryBuilder.should(queryBuilder1).should(queryBuilder2);
                query.must(queryBuilder);
            }

            // 3:收货地：<input name="recAddress"
            if(StringUtils.isNotBlank(wayBill.getRecAddress())){
                QueryBuilder queryBuilder1 = new WildcardQueryBuilder("recAddress", "*"+wayBill.getRecAddress()+"*");
                QueryBuilder queryBuilder2 = new QueryStringQueryBuilder(wayBill.getRecAddress()).field("recAddress").defaultOperator(Operator.AND);// 将搜素的结果进行合并
                BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
                queryBuilder.should(queryBuilder1).should(queryBuilder2);
                query.must(queryBuilder);
            }

            // 4:快递产品类型：<select class="easyui-combobox" style="width:150px" name="sendProNum">
            if(StringUtils.isNotBlank(wayBill.getSendProNum())){
                QueryBuilder queryBuilder = new TermQueryBuilder("sendProNum", wayBill.getSendProNum());
                query.must(queryBuilder);
            }

            // 5:运单状态：<select class="easyui-combobox" style="width:150px" name="signStatus">
            if(wayBill.getSignStatus()!=null && wayBill.getSignStatus()!=0){
                QueryBuilder queryBuilder = new TermQueryBuilder("signStatus", wayBill.getSignStatus());
                query.must(queryBuilder);
            }
            SearchQuery searchQuery = new NativeSearchQuery(query); // 拼装多个查询条件
            Pageable pageable = new PageRequest(0, 10000);//从第一页开始检索，10000表示导出excel的最大数据
            // 添加分页
            searchQuery.setPageable(pageable);
            Page<WayBill> page = wayBillIndexRepository.search(searchQuery);
            return page.getContent();
        }
    }

    @Override
    public List<Object[]> findByHighCharts() {

        return wayBillRepository.findByHighCharts();
    }

}